package com.ai.bitcoin.jpa.service;

import com.ai.bitcoin.bo.BccNewsTop5BO;
import com.ai.bitcoin.constant.JwtConstant;
import com.ai.bitcoin.exception.BusinessException;
import com.ai.bitcoin.jpa.dao.BccUserBonusConfigDao;
import com.ai.bitcoin.jpa.dao.BccUserBonusLogDao;
import com.ai.bitcoin.jpa.dao.BccUserDao;
import com.ai.bitcoin.jpa.dao.BccUserWeixinGroupDao;
import com.ai.bitcoin.jpa.entity.*;
import com.ai.bitcoin.service.MemberCenterService;
import com.ai.bitcoin.util.IdGeneration;
import com.ai.bitcoin.util.JwtUtil;
import com.ai.bitcoin.utils.HttpClientUtils;
import com.ai.bitcoin.vo.BccNewsTop5VO;
import com.ai.bitcoin.vo.UserEncourageReq;
import com.ai.bitcoin.vo.UserEncourageResponse;
import com.ai.bitcoin.vo.WeixinGroupVo;
import com.ai.bitcoin.weixin.template.BonusChangeTemplate;
import com.ai.bitcoin.weixin.template.SendReportService;
import com.ai.bitcoin.weixin.template.TemplateManager;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.logging.log4j.core.util.UuidUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.*;

import static com.ai.bitcoin.jpa.entity.BccUserBonusConfig.*;

/**
 * 用户奖励服务类
 */
@Service
@Slf4j
public class UserBonusService {

    @Value("${wx.coin.report.template.id}")
    private String mpReportTemplateId;
    @Autowired
    BccNewsService bccNewsService;
    @Autowired
    BccUserDao bccUserDao;
    @Autowired
    BccBasicInfoService bccBasicInfoService;
    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    MemberCenterService memberCenterService;

    /**
     *
     */
    private final BccUserBonusConfigDao bonusConfigDao;
    private final BccUserDao userDao;
    private final SendReportService sendReportService;
    private final BccUserWeixinGroupDao weixinGroupDao;
    @Getter
    private final BccUserBonusLogDao bccUserBonusLogDao;
    private final BccSubCoinService subCoinService;

    @Autowired
    public UserBonusService(BccUserBonusConfigDao bonusConfigDao, BccUserDao userDao, BccUserWeixinGroupDao wechatGroupDao, BccUserBonusLogDao bccUserBonusLogDao, SendReportService sendReportService, BccSubCoinService subCoinService) {
        this.bonusConfigDao = bonusConfigDao;
        this.userDao = userDao;
        this.weixinGroupDao = wechatGroupDao;
        this.bccUserBonusLogDao = bccUserBonusLogDao;
        this.sendReportService = sendReportService;
        this.subCoinService = subCoinService;
    }


    //积分变动公众号通知
    public UserEncourageResponse sendBonus(String eventSourceCd, String eventTypeCd, UserEncourageReq request) {
        String logPre = "用户激励请求[" + UuidUtil.getTimeBasedUuid().toString() + "]:";
        log.info("请求来源：{} 请求event：{} 参数{}", logPre, eventSourceCd, eventTypeCd, request);

        //记住请求来源
        request.setEventSourceCd(eventSourceCd);
        // 0. 奖励用户
        Optional<BccUser> userOptional;
        UserEncourageResponse response = new UserEncourageResponse();
        response.setBccBasicInfo(request.getBccBasicInfo());
        response.setEventSourceCd(eventSourceCd);
        response.setOpenId(request.getOpenId());
        response.setEventTypeCd(eventTypeCd);
        //取得用户
        if (StringUtils.equals(eventSourceCd, BccUserBonusConfig.EVENT_SOURCE_GROUP)) {
            userOptional = getUserByGroupInfo(request, response, logPre);
        }
        else if (StringUtils.isNotEmpty(request.getOpenId())) {
            log.info("{}识别为已关联公众号用户发送消息", logPre);
            userOptional = Optional.ofNullable(userDao.findByOpenId(request.getOpenId()));
            //补全 关注公众号未插入数据的用户数据
            if (!userOptional.isPresent()) {
                log.warn("{}公众号用户数据不存在", logPre);
                BccUser bccUser = new BccUser();
                request.setNewUser(true);
                bccUser.setOpenId(request.getOpenId());
                bccUser.setNickname(request.getNickname());
                String symbol = IdGeneration.getUniqueSign();
                bccUser.setBonus(0d);
                bccUser.setSymbol(symbol);
                bccUser = userDao.save(bccUser);
                userOptional = Optional.of(bccUser);
            }
        }
        else {
            log.warn("{}无法识别用户", logPre);
            return response;
        }

        userOptional.ifPresent((user) -> {
            //用户无推荐人并且不是自己推荐 更新用户推荐人
            if (StringUtils.isEmpty(user.getParentOpenId()) && StringUtils.isNotEmpty(request.getParentOpenId()) && !StringUtils.equals(request.getParentOpenId(), user.getOpenId())) {
                user.setParentOpenId(request.getParentOpenId());
                user = userDao.save(user);
                log.info("{} 更新用户parentOpenId", logPre);

                //奖励推荐人
                UserEncourageReq req = new UserEncourageReq();
                req.setOpenId(request.getParentOpenId());
                sendBonus(BccUserBonusConfig.EVENT_SOURCE_MP, "0103", req);
            }
            log.info("{}用户激励前PLC数量", logPre);
            //设置当前PLC总数
            response.setCurrentBonusCount(BigDecimal.valueOf(user.getBonus()));
            log.info("2  {}", response.getCurrentBonusCount());
        });

        BccUserBonusConfig config = bonusConfigDao.findByEventTypeCd(eventTypeCd);


        // 1.取得可发放的奖励
        // TODO 2.区分奖励类型是全部发放还是按优先级发放 当前全部发放

        userOptional.ifPresent((user) -> {
            request.setUserId(user.getId());
            request.setOpenId(user.getOpenId());
            //我的邀请海报回复图片
            if (StringUtils.equals(eventTypeCd, "0311") && StringUtils.isNotEmpty(user.getOpenId())) {
                try {
                    response.getImageList().add(memberCenterService.getPosterUrl(user.getOpenId()));
                } catch (IOException ignored) {
                }
//                response.getImageList().add("https://pan.baidu.com/box-static/disk-header/header/img/logo@2x.png");

                return;
            }
            //无奖励类型 直接回复内容
            if (StringUtils.equals(config.getBonusTypeCd(), BccUserBonusConfig.BONUS_TYPE_NONE)) {
                log.info("{}无奖励类型直接回复标准内容", logPre);
                response.getMessageList().add(config.getSuccessReplayContent());
            }
            else {
                //判断是否已发放此奖励
                if (checkRecord(request, config, response)) {
                    log.info("{}验证当前用户可以获得PLC奖励", logPre);
                    // 4.更新奖励信息
                    processBonus(config, user, request, response);

                    //无奖励类型 直接回复内容
                    if (StringUtils.isEmpty(user.getOpenId())) {
                        log.info("{}无OpenId用户", logPre);
                        response.getMessageList().clear();
                        response.getMessageList().add(config.getUnsubscribeReplayContent());
                    }
                }
                else if (StringUtils.equals(config.getEventTypeCd(), "0306")) {
                    UserEncourageResponse encourageResponse = sendBonus(config.getEventSourceCd(), "0307", request);
                    response.setMessageList(encourageResponse.getMessageList());
                    response.setResult(encourageResponse.getResult());
                }
                else {
                    response.setResult(2);
                    log.info("{}验证当前用户已不可获得PLC奖励", logPre);
                }
            }

            log.info("{}用户激励后PLC数量", logPre);
            //设置当前PLC总数
            response.setCurrentBonusCount(BigDecimal.valueOf(user.getBonus()));
            log.info("1  {}", response.getCurrentBonusCount());
        });


        if (StringUtils.equals(response.getEventTypeCd(), "0306") && response.getResult() == 1) {
            try {
                int result = subCoinService.subscribeBccService(request.getOpenId(), response.getBccBasicInfo().getBccId(), 1);
                if (result == 1) {
                    response.setSubscribeTypeName("订阅");
                }
                else if (result == 2) {
                    response.setSubscribeTypeName("续订");
                }
            } catch (BusinessException e) {
                log.warn(e.getMessage(), e);
            }
        }

        // 6.返回回复信息
        formatMessageList(request, response);
        log.info("{}回复消息:\n\r{}", logPre, response.getMessageList());
        return response;
    }

    /**
     * 根据组信息取得关联用户
     */
    private Optional<BccUser> getUserByGroupInfo(UserEncourageReq request, UserEncourageResponse response, String logPre) {
        log.info("{}识别为群组来源", logPre);
        Optional<BccUser> userOptional;
        BccUserWeixinGroup bccUserWeixinGroup;
        if (StringUtils.isNotEmpty(request.getParentNickname())) {
            log.info("{}识别为邀人进群", logPre);
            response.setSender(request.getParentNickname());
            response.setInviterName(request.getParentNickname());
            response.setBeInvitedUserNme(request.getNickname());
            //取得邀请人信息
            bccUserWeixinGroup = weixinGroupDao.findByGroupNameAndNickname(request.getParentNickname(), request.getGroupName());
        }
        else {
            log.info("{}识别为群成员发送消息", logPre);
            response.setSender(request.getNickname());
            response.setInviterName(request.getParentNickname());
            //取得群友组信息
            bccUserWeixinGroup = weixinGroupDao.findByGroupNameAndNickname(request.getNickname(), request.getGroupName());
        }

        if (bccUserWeixinGroup != null) {
            log.info("{}取得微信群人员组信息", logPre, bccUserWeixinGroup);
            //有OpenId使用OpenId 无openId取userId
            if (StringUtils.isNotEmpty(bccUserWeixinGroup.getOpenId())) {
                userOptional = Optional.ofNullable(userDao.findByOpenId(bccUserWeixinGroup.getOpenId()));
            }
            else if (StringUtils.isNotEmpty(bccUserWeixinGroup.getUserId())) {
                userOptional = userDao.findById(bccUserWeixinGroup.getUserId());
            }
            else {
                log.warn("{}群组人员信息未关联用户信息 新增用户并关联:{}", logPre, bccUserWeixinGroup);
                BccUser bccUser = new BccUser();
                bccUser.setNickname(request.getNickname());
                String symbol = IdGeneration.getUniqueSign();
                bccUser.setSymbol(symbol);
                bccUser.setBonus(0d);
                bccUser = userDao.save(bccUser);
                bccUserWeixinGroup.setUserId(bccUser.getId());
                weixinGroupDao.save(bccUserWeixinGroup);
                userOptional = Optional.of(bccUser);
                //新用户关注
                request.setNewUser(true);
            }
        }
        else {
            log.info("{}未找到群员信息", logPre);
            //查找群主信息
            BccUserWeixinGroup ownerGroup = weixinGroupDao.findByGroupNameAndGroupOwnerNameAndNickname(request.getGroupName(), request.getGroupOwnerName(), request.getGroupOwnerName());
            if (ownerGroup != null) {
                log.info("{}定位到群主新增成员,", logPre);
                BccUser bccUser = new BccUser();
                bccUser.setNickname(request.getNickname());
                String symbol = IdGeneration.getUniqueSign();
                bccUser.setBonus(0d);
                bccUser.setSymbol(symbol);
                bccUser = userDao.save(bccUser);
                bccUserWeixinGroup = new BccUserWeixinGroup();
                bccUserWeixinGroup.setGroupName(ownerGroup.getGroupName());
                bccUserWeixinGroup.setGroupOwnerName(ownerGroup.getGroupOwnerName());
                bccUserWeixinGroup.setNickname(request.getNickname());
                bccUserWeixinGroup.setCreateTime(new Date());
                bccUserWeixinGroup.setUserId(bccUser.getId());
                weixinGroupDao.save(bccUserWeixinGroup);
                userOptional = Optional.of(bccUser);
            }
            else {
                log.info("{}无群主信息新增成员,", logPre);
                BccUser bccUser = new BccUser();
                bccUser.setNickname(request.getNickname());
                String symbol = IdGeneration.getUniqueSign();
                bccUser.setBonus(0d);
                bccUser.setSymbol(symbol);
                bccUser = userDao.save(bccUser);
                bccUserWeixinGroup = new BccUserWeixinGroup();
                bccUserWeixinGroup.setGroupName(request.getGroupName());
                bccUserWeixinGroup.setGroupOwnerName(request.getGroupOwnerName());
                bccUserWeixinGroup.setNickname(request.getNickname());
                bccUserWeixinGroup.setCreateTime(new Date());
                bccUserWeixinGroup.setUserId(bccUser.getId());
                weixinGroupDao.save(bccUserWeixinGroup);
                userOptional = Optional.of(bccUser);
            }
        }
        return userOptional;
    }

    @Transactional
    public void processBonus(BccUserBonusConfig config, BccUser user, UserEncourageReq request, UserEncourageResponse response) {
        BigDecimal receiveBonusNumber = config.getNumber();
        //发放用户奖励
        if (!Objects.equals(receiveBonusNumber, BigDecimal.ZERO)) {
            BigDecimal userBonus = BigDecimal.valueOf(user.getBonus()).add(receiveBonusNumber);
            if (userBonus.compareTo(BigDecimal.ZERO) < 0) {
                response.setResult(3);
                if (StringUtils.isNotEmpty(config.getErrorReplayContent())) {
                    response.getMessageList().add(config.getErrorReplayContent());
                }
                return;
            }

            user.setBonus(userBonus.doubleValue());
            user = userDao.save(user);
            //记录用户奖励
            saveUserBonusLog(config, user, receiveBonusNumber);
            //设置获取奖励
            response.setReceiveBonusNumber(receiveBonusNumber);
            response.setResult(1);
            //回复使用次数奖励
            if (StringUtils.isNotEmpty(config.getSuccessReplayContent())) {
                response.getMessageList().clear();
                response.getMessageList().add(config.getSuccessReplayContent());
            }
            //公众号用户通知积分变更
            if (StringUtils.isNotEmpty(user.getOpenId())) {
                //如果是回复关键词 和签到 不需要通知
                if (!StringUtils.equals(config.getEventTypeCd(), "0102") &&
                        !StringUtils.equals(config.getEventTypeCd(), "0104") &&
                        !StringUtils.equals(config.getEventTypeCd(), "0306") &&
                        !StringUtils.equals(config.getEventTypeCd(), "0307")
                ) {
                    noticeBonusChangeMessage(user.getOpenId(), config.getEventTypeName(), receiveBonusNumber, userBonus);
                }
            }
        }

        //回复未授权消息
        if (StringUtils.isEmpty(user.getOpenId())) {
            response.setResult(3);
            //回复使用次数奖励
            if (StringUtils.isNotEmpty(config.getUnsubscribeReplayContent())) {
                response.getMessageList().clear();
                response.getMessageList().add(config.getUnsubscribeReplayContent());
            }
            return;
        }

        if (StringUtils.equals(config.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_GROUP)  //微信群来源
                &&
                receiveBonusNumber.compareTo(BigDecimal.ZERO) > 0
                &&
                StringUtils.isNotEmpty(config.getParentId())//需要发放群主奖励
        ) {
            //群主奖励
            BccUserWeixinGroup bccUserWeixinGroup = weixinGroupDao.findByGroupNameAndGroupOwnerNameAndNickname(request.getGroupName(), request.getGroupOwnerName(), request.getGroupOwnerName());
            if (bccUserWeixinGroup != null) {
                BccUser u = userDao.findByOpenId(bccUserWeixinGroup.getOpenId());
                BigDecimal groupOwnerBonus = receiveBonusNumber.multiply(BigDecimal.valueOf(0.1));
                u.setBonus(BigDecimal.valueOf(u.getBonus()).add(groupOwnerBonus).doubleValue());
                u = userDao.save(u);
                //记录群主奖励
                saveUserBonusLog(config, u, groupOwnerBonus, true);
                String reason = config.getEventTypeName() + "【" + request.getGroupOwnerName() + "】群主奖励";
                noticeBonusChangeMessage(u.getOpenId(), reason, groupOwnerBonus, BigDecimal.valueOf(u.getBonus()));
            }
        }
    }

    /**
     * 记录用户信息变动日志
     *
     * @param config 奖励信息
     * @param user   奖励用户
     * @param bonus  奖励数量
     */
    private void saveUserBonusLog(BccUserBonusConfig config, BccUser user, BigDecimal bonus) {
        saveUserBonusLog(config, user, bonus, false);
    }

    private void saveUserBonusLog(BccUserBonusConfig config, BccUser user, BigDecimal bonus, boolean noUniqueKey) {
        BccUserBonusLog log = new BccUserBonusLog();
        log.setEventTypeCd(config.getEventTypeCd());
        log.setOpenId(user.getOpenId());
        log.setTotalKey(config.getTotalKey());
        if (!noUniqueKey) {
            log.setUniqueKey(config.getUniqueKey());
        }
        log.setEventDate(new Date());
        log.setBonusNumber(bonus);
        log.setTotalPlc(BigDecimal.valueOf(user.getBonus()));
        log.setConfig(config);
        bccUserBonusLogDao.save(log);
    }

    /**
     * 验证奖励 方法同步
     *
     * @param request  请求信息
     * @param config   奖励信息
     * @param response 返回信息
     * @return true 可发放奖励 false 不可发放奖励
     */
    private synchronized boolean checkRecord(UserEncourageReq request, BccUserBonusConfig config, UserEncourageResponse response) {

        if (StringUtils.equals(config.getEventTypeCd(), "0101") && !request.isNewUser()) {
            //老用户重新关注
            response.getMessageList().add(config.getErrorReplayContent());
            return false;
        }

        //阅读自己分享的文章无奖励
        if (Objects.equals(config.getEventTypeCd(), "0302") &&
                Objects.equals(request.getArticleOpenId(), request.getOpenId())) {
            //阅读自己分享的文章无奖励
            return false;
        }

        if (Objects.equals(config.getBonusTypeCd(), BONUS_TYPE_NONE)) {
            //无奖励的配置直接通过验证
            return true;
        }
        config.setTotalKey(getTotalKey(request, config));
        config.setUniqueKey(getUniqueKey(request, response, config));

        if (config.getBonusTimes() > 0) {
            //已使用奖励次数
            long hasUsedTimes = bccUserBonusLogDao.countByTotalKey(config.getTotalKey());
            //次数已用尽
            if (hasUsedTimes >= config.getBonusTimes()) {
                if (StringUtils.isNotEmpty(config.getErrorReplayContent())) {
                    //增加次数已用尽消息
                    response.getMessageList().add(config.getErrorReplayContent());
                }
                return false;
            }
            else {
                response.setBonusTimes(config.getBonusTimes() - hasUsedTimes - 1);
            }
        }

        //有唯一奖励奖励的配置并且已发放奖励
        return !StringUtils.isNotEmpty(config.getUniqueKey()) || !bccUserBonusLogDao.existsByUniqueKey(config.getUniqueKey());
    }

    /**
     * 取得统计的KEY
     *
     * @param request 请求
     * @param config  配置
     * @return
     */
    public String getTotalKey(UserEncourageReq request, BccUserBonusConfig config) {
        //验证次数
        String todayYMD = DateFormatUtils.format(new Date(), "yyyy/MM/dd");
        String totalKey;
        switch (config.getBonusUnitTypeCd()) {
            case UNIT_TYPE_TIME_USER:
                totalKey = request.getUserId();
                break;
            case UNIT_TYPE_TIME_USER_DAY:
            case UNIT_TYPE_TIME_USER_GROUP:
            case UNIT_TYPE_TIME_USER_ARTICLE:
                totalKey = request.getUserId() + "_" + todayYMD;
                break;
            case UNIT_TYPE_TIME_USER_ARTICLE_CLICK:
                //每个用户每篇文章只有效一次
                totalKey = request.getArticleOpenId() + "_" + todayYMD + "_" + request.getOpenId();
                break;
            default:
                totalKey = request.getOpenId();
        }
        totalKey = config.getEventTypeCd() + "_" + totalKey;
        //已使用奖励次数
        return totalKey;
    }

    /**
     * 取得统计的KEY
     *
     * @param request 请求
     * @param config  配置
     * @return
     */
    public String getUniqueKey(UserEncourageReq request, UserEncourageResponse response, BccUserBonusConfig config) {
        //验证次数
        String todayYMD = DateFormatUtils.format(new Date(), "yyyy/MM/dd");
        String uniqueKey = null;
        switch (config.getBonusUnitTypeCd()) {
            case UNIT_TYPE_TIME_USER:
                //每个用户算一次
                uniqueKey = null;
                break;
            case UNIT_TYPE_TIME_USER_DAY:
                //不需要唯一
                break;
            case UNIT_TYPE_TIME_USER_GROUP:
                //用昵称做唯一限制
                uniqueKey = request.getNickname();
                //被邀人昵称做唯一限制
                if (StringUtils.isNotEmpty(response.getBeInvitedUserNme())) {
                    uniqueKey = response.getBeInvitedUserNme();
                }
                break;
            case UNIT_TYPE_TIME_USER_ARTICLE:
                //每篇文章算一次
                uniqueKey = request.getUserId() + "_" + todayYMD + "_" + request.getNewsId();
                break;
            case UNIT_TYPE_TIME_USER_ARTICLE_CLICK:
                //阅读人+文章唯一
                uniqueKey = request.getArticleOpenId() + "_" + request.getNewsId();
                break;
        }
        if (StringUtils.isNotEmpty(uniqueKey)) {
            return config.getEventTypeCd() + "_" + uniqueKey;
        }
        else {
            return null;
        }
    }

    /**
     * 格式化模板信息
     */
    private void formatMessageList(UserEncourageReq request, UserEncourageResponse response) {
        List<String> messageList = Lists.newArrayList();
        for (String message : response.getMessageList()) {
            if (StringUtils.contains(message, "${剩余奖励次数}")) {
                message = StringUtils.replace(message, "${剩余奖励次数}", String.valueOf(response.getBonusTimes()));
            }

            if (StringUtils.contains(message, "${剩余奖励次数}")) {
                message = StringUtils.replace(message, "${剩余奖励次数}", String.valueOf(response.getBonusTimes()));
            }

            if (StringUtils.contains(message, "${订阅续订}") && response.getSubscribeTypeName() != null) {
                message = StringUtils.replace(message, "${订阅续订}", response.getSubscribeTypeName());
            }

            if (StringUtils.contains(message, "${发送人}")) {
                if (StringUtils.isNotEmpty(response.getSender())) {
                    message = StringUtils.replace(message, "${发送人}", response.getSender());
                }
                else {
                    message = StringUtils.replace(message, "@${发送人}", "");
                }
            }

            if (StringUtils.contains(message, "${群名}") && request.getGroupName() != null) {
                message = StringUtils.replace(message, "${群名}", request.getGroupName());
            }

            if (response.getInviterName() != null) {
                message = StringUtils.replace(message, "${邀请人}", response.getInviterName());
            }

            if (response.getBeInvitedUserNme() != null) {
                message = StringUtils.replace(message, "${被邀请人}", response.getBeInvitedUserNme());
            }

            if (response.getCurrentBonusCount() != null) {
                message = StringUtils.replace(message, "${当前PLC总数}", response.getCurrentBonusCount().toString());
            }
            if (response.getReceiveBonusNumber() != null) {
                message = StringUtils.replace(message, "${获得PLC数量}", response.getReceiveBonusNumber().abs().toString());
            }
            if (response.getBccBasicInfo() != null) {
                String bccName = response.getBccBasicInfo().getNameEn();
                if (StringUtils.isNotEmpty(response.getBccBasicInfo().getNameCn())) {
                    bccName = response.getBccBasicInfo().getNameCn() + "/" + bccName;
                }
                message = StringUtils.replace(message, "${BCC名称}", bccName);
                String reportUrl = MessageFormat.format("https://www.valuechain.group/template/coinIndex/coinIndex.html?bccId={0}&symbol={1}", response.getBccBasicInfo().getBccId(), response.getBccBasicInfo().getSymbol());
                message = StringUtils.replace(message, "${BCC报告地址}", HttpClientUtils.getShortUrl(reportUrl));
                if (StringUtils.isNotEmpty(response.getBccBasicInfo().getVoiceUrl())) {
                    message = StringUtils.replace(message, "${BCC音频地址}", HttpClientUtils.getShortUrl(response.getBccBasicInfo().getVoiceUrl()));
                }
            }

            if (StringUtils.contains(message, "${个人PLC排名}") && response.getPersonalTopIndex() == null) {
                //获取个人PLC排名
                response.setPersonalTopIndex(getPersonalTopIndex(request.getUserId()));
            }
            if (response.getPersonalTopIndex() != null) {
                message = StringUtils.replace(message, "${个人PLC排名}", response.getPersonalTopIndex().toString());
            }

            if (StringUtils.contains(message, "${支持的币列表}") && response.getSupportBccList() == null) {
                //支持的币列表
                response.setSupportBccList(getSupportBccList());
            }
            if (response.getSupportBccList() != null) {
                message = StringUtils.replace(message, "${支持的币列表}", StringUtils.join(response.getSupportBccList(), ","));
            }

            if (StringUtils.contains(message, "${情报列表}") && response.getReportList() == null) {
                //BCC存在则获取情报信息
                response.setReportList(getBccReport(request, response));
            }

            if (response.getReportList() != null) {
                message = StringUtils.replace(message, "${情报列表}", response.getReportList());
            }

            if (StringUtils.contains(message, "${待领取PLC列表}") && response.getWaitReceiveBonusList() == null) {
                //获取剩余PLC列表
                response.setWaitReceiveBonusList(getWaitReceiveBonusList(request, response));
            }

            if (response.getWaitReceiveBonusList() != null) {
                message = StringUtils.replace(message, "${待领取PLC列表}", response.getWaitReceiveBonusList());
            }

            if (StringUtils.contains(message, "${群关联公众号地址}")) {
                //生成token
                WeixinGroupVo vo = new WeixinGroupVo();
                vo.setType(9999);
                vo.setUserId(request.getUserId());
                if (StringUtils.isNotEmpty(request.getParentNickname())) {
                    vo.setNickname(request.getParentNickname());
                }
                else {
                    vo.setNickname(request.getNickname());
                }
                vo.setGroupname(request.getGroupName());
                vo.setGroupOwnerName(request.getGroupOwnerName());
                String token = jwtUtil.createToken(vo, JwtConstant.JWT_REFRESH_TTL);
                //获取剩余PLC列表
                String url = HttpClientUtils.getShortUrl("https://www.valuechain.group/template/empty.html?state=" + token);
                message = StringUtils.replace(message, "${群关联公众号地址}", url);
            }

            messageList.add(message);
        }
        response.setMessageList(messageList);
    }

    //取得已使用次数
    public long getUsedTimes(UserEncourageReq request, BccUserBonusConfig config) {
        String totalKey = getTotalKey(request, config);
        config.setTotalKey(totalKey);
        return bccUserBonusLogDao.countByTotalKey(totalKey);
    }

    //支持的币列表
    private List<String> getSupportBccList() {
        return bccBasicInfoService.getDao().findAllBccSymbol();
    }


    //取得当前排名 TODO 优化
    private int getPersonalTopIndex(String userId) {
        return bccUserDao.computeMyRankByUserId(userId);
    }

    /**
     * 取得待领取PLC
     *
     * @param request 请求
     * @return 待领取PLC回复内容
     */
    private String getWaitReceiveBonusList(UserEncourageReq request, UserEncourageResponse response) {
        //所有有次数限制的奖励
        List<BccUserBonusConfig> configList = bonusConfigDao.findByEventSourceCdInAndBonusTimesGreaterThanOrderByPriAsc(Lists.newArrayList(response.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_SHARE), 0);
        //拼接返回信息
        StringBuilder content = new StringBuilder();
        for (BccUserBonusConfig config : configList) {
            //剩余可用次数
            long times = config.getBonusTimes() - getUsedTimes(request, config);
            if (times <= 0) {
                continue;
            }

            //如果openId不为空并且 为0101关注奖励则忽略
            if (StringUtils.equals(config.getEventTypeCd(), "0101") && StringUtils.isNotEmpty(request.getOpenId())) {
                continue;
            }

            content.append("【").append(config.getEventTypeName()).append("】还剩").append(times).append("次");
            if (!StringUtils.equals(config.getBonusTypeCd(), "03")) {
                content.append(",最高可获得").append(config.getMaxNumber().multiply(BigDecimal.valueOf(times))).append("PLC");
            }
            //配置示例URL场合增加查看示例地址内容
            if (StringUtils.isNotEmpty(config.getLinkUrl())) {
                //替换公众部分
                String linkUrl = HttpClientUtils.getShortUrl(StringUtils.replace(config.getLinkUrl(), "%s",
                        StringUtils.equals(request.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_MP) ? "gong" : "wei")
                );
                //公众号回复使用超链接
                if (StringUtils.equals(request.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_MP)) {
                    content.append(",<a href='").append(linkUrl).append("'>查看示例</a>");
                }
                else {
                    content.append(",查看示例 ").append(linkUrl);
                }
            }
            content.append("\n\n");
        }
        return content.toString();
    }

    /**
     * 取得BCC报告
     */
    private String getBccReport(UserEncourageReq request, UserEncourageResponse response) {
        BccBasicInfo bccBasicInfo = response.getBccBasicInfo();
        if (bccBasicInfo == null) {
            return null;
        }
        BccNewsTop5BO newsBo = new BccNewsTop5BO();
        newsBo.setBccId(bccBasicInfo.getBccId());
        BccNewsTop5VO newsList = bccNewsService.getTop3BccNewsBccId(newsBo);
        StringBuilder content = new StringBuilder();
        for (BccNews news : newsList.getBccNewsList()) {
            if (StringUtils.equals(request.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_MP)) {
                content.append(news.getTitle()).
                        append("(<a href='").append(HttpClientUtils.getShortUrl(
                        "https://www.valuechain.group/template/newsDetail.html?type=1&bccId=" + bccBasicInfo.getBccId() + "&id=" + news.getId())
                ).append("'>查看详情</a>,可继续获得PLC奖励)\n\n");
            }
            else {
                content.append(news.getTitle()).
                        append(" ,查看详情 ").append(HttpClientUtils.getShortUrl(
                        "https://www.valuechain.group/template/newsDetail.html?type=1&bccId=" + bccBasicInfo.getBccId() + "&id=" + news.getId())
                ).append(" ,可继续获得PLC奖励)\n\n");
            }

        }
        if (StringUtils.equals(request.getEventSourceCd(), BccUserBonusConfig.EVENT_SOURCE_MP)) {
            content.append("更多").append(bccBasicInfo.getSymbol()).append("情报请 <a href='").append(HttpClientUtils.getShortUrl(
                    "https://www.valuechain.group/template/message_center/msgCenterSingle.html?bccid=" + bccBasicInfo.getBccId())
            ).append("'>点击</a> \n\n");
        }
        else {
            content.append("更多").append(bccBasicInfo.getSymbol()).append("情报请点击 ").append(HttpClientUtils.getShortUrl(
                    "https://www.valuechain.group/template/message_center/msgCenterSingle.html?bccid=1" + bccBasicInfo.getBccId())
            ).append("\n\n");
        }

        return content.toString();
    }

    /**
     * 积分变更通知
     *
     * @param openId       openId
     * @param reason       变更理由
     * @param changeBonus  变更数值
     * @param currentBonus 最新积分
     */
    public void noticeBonusChangeMessage(String openId, String reason, BigDecimal changeBonus, BigDecimal currentBonus) {
        try {
            Map<String, Object> messageMap = new HashMap<>();
            messageMap.put("openId", openId);
            messageMap.put("url", "http://explorelife.vip/bitcoin/bitcoin/media/" + openId + ".png");
            messageMap.put("first", "您的积分(PLC)变动如下");
            messageMap.put("FieldName", "变更原因");
            messageMap.put("Account", reason);
            messageMap.put("change", changeBonus.compareTo(BigDecimal.ZERO) >= 0 ? "增加" : "减少");
            messageMap.put("CreditChange", changeBonus);
            messageMap.put("CreditTotal", currentBonus);
            sendReportService.sendTemplateMsg(TemplateManager.buildTemplateParater(new BonusChangeTemplate(), messageMap));
        } catch (Exception e) {
            log.warn("通知消息变更通知异常", e);
        }

    }
}
